﻿using System;
using System.Runtime.Serialization;
using System.Json;
using System.Xml.Linq;
using System.Xml.Serialization;

namespace MailRuWrapper.Client
{
    [DataContract(Name = "User")]
    [XmlRoot(ElementName = "user")]
    public class User : IUser
    {
        #region Implementation of IUser

        [DataMember(Name = "uid")]
        [XmlElement(ElementName = "uid")]
        public string Uid { get; private set; }

        [DataMember(Name = "first_name")]
        [XmlElement(ElementName = "first_name")]
        public string FirstName { get; private set; }

        [DataMember(Name = "last_name")]
        [XmlElement(ElementName = "last_name")]
        public string LastName { get; private set; }

        [DataMember(Name = "nick")]
        [XmlElement(ElementName = "nick")]
        public string Nick { get; private set; }

        [DataMember(Name = "sex")]
        [XmlElement(ElementName = "sex")]
        public Gender Sex { get; private set; }

        [DataMember(Name = "birthday")]
        [XmlElement(ElementName = "birthday")]
        public DateTime Birthday { get; private set; }

        [DataMember(Name = "pic")]
        [XmlElement(ElementName = "pic")]
        public Uri Pic { get; private set; }

        [DataMember(Name = "pic_small")]
        [XmlElement(ElementName = "pic_small")]
        public Uri PicSmall { get; private set; }

        [DataMember(Name = "pic_big")]
        [XmlElement(ElementName = "pic_big")]
        public Uri PicBig { get; private set; }

        [DataMember(Name = "link")]
        [XmlElement(ElementName = "link")]
        public Uri Link { get; private set; }

        [DataMember(Name = "referer_type")]
        [XmlElement(ElementName = "referer_type")]
        public RefererTypes RefererType { get; private set; }

        [DataMember(Name = "referer_id")]
        [XmlElement(ElementName = "referer_id")]
        public string RefererId { get; private set; }


        public Uri StatusAgent { get { return new Uri(this.StatusAgent()); } }

        public string MailAdress { get { return this.MailAddress(); } }

        public string FullName
        {
            get { return FirstName + " " + LastName; }
        }

        public bool IsReferred
        {
            get { return RefererType.IsReferred(); }
        }

        #endregion

        internal static IUser Parse(JsonValue jObject)
        {
            if (jObject.JsonType == JsonType.Object)
            {
                var _user = new User
                                {
                                    Uid = jObject["uid"],
                                    FirstName = jObject["first_name"],
                                    LastName = jObject["last_name"],
                                    Nick = jObject["nick"],
                                    Sex = (Gender) (int) jObject["sex"],
                                    Birthday = jObject["birthday"].ToDateTime(),
                                    Pic = jObject["pic"],
                                    PicSmall = jObject["pic_small"],
                                    PicBig = jObject["pic_big"],
                                    Link = jObject["link"],
                                    RefererType = ((string) jObject["referer_type"]).ToRefererType(),
                                    RefererId = jObject["referer_id"].ToString()
                                };
                return _user;
            }
            return jObject.JsonType == JsonType.String ? new User {Uid = (string) jObject} : null;
        }

        internal static IUser Parse(XElement element)
        {
            if (element.HasElements)
            {
                var _result = new User
                {
                    Uid = element.Element("uid").Value,
                    Birthday = element.Element("birthday").Value.ToDateTime(),
                    FirstName = element.Element("first_name").Value,
                    LastName = element.Element("last_name").Value,
                    Link = element.Element("link").Value.ToUri(),
                    Nick = element.Element("nick").Value,
                    Pic = element.Element("pic").Value.ToUri(),
                    PicBig = element.Element("pic_big").Value.ToUri(),
                    PicSmall = element.Element("pic_small").Value.ToUri(),
                    Sex = (Gender)element.Element("sex").Value.ToInt(),
                    RefererType = element.Element("referer_type").Value.ToRefererType(),
                    RefererId = element.Element("referer_id").Value
                };

                return _result;
            }

            return new User { Uid = element.Value };
        }

        public override string ToString()
        {
            return String.IsNullOrEmpty(Nick) ? Uid : Nick;
        }
    }

    [DataContract(Name = "PhotoAlbum")]
    public class PhotoAlbum : IPhotoAlbum
    {
        #region Implementation of IPhotoAlbum

        [DataMember(Name = "aid")]
        public string Aid { get; private set; }
        [DataMember(Name = "cover_pid")]
        public string CoverPid { get; private set; }
        [DataMember(Name = "owner")]
        public string Owner { get; private set; }
        [DataMember(Name = "title")]
        public string Title { get; private set; }
        [DataMember(Name = "description")]
        public string Description { get; private set; }
        [DataMember(Name = "created")]
        //    [JsonConverter(typeof(DateTimeConverter))]
        public DateTime Created { get; private set; }
        [DataMember(Name = "updated")]
        //    [JsonConverter(typeof(DateTimeConverter))]
        public DateTime Updated { get; private set; }
        [DataMember(Name = "size")]
        public int Size { get; private set; }
        [DataMember(Name = "privacy")]
        public Privacy Privacy { get; private set; }

        #endregion

        public static IPhotoAlbum Parse(JsonValue jObject)
        {
            var _result = new PhotoAlbum
                              {
                                  Aid = jObject["aid"],
                                  CoverPid = jObject["cover_pid"],
                                  Owner = jObject["owner"],
                                  Title = jObject["title"],
                                  Description = jObject["description"],
                                  Created = jObject["created"].ToDateTime(),
                                  Updated = jObject["updated"].ToDateTime(),
                                  Size = jObject["size"].ToInt(),
                                  Privacy = (Privacy)jObject["privacy"].ToInt()
                              };
            return _result;
        }

        public static IPhotoAlbum Parse(XElement element)
        {
            var _result = new PhotoAlbum
            {
                Aid = element.Element("aid").Value,
                CoverPid = element.Element("cover_pid").Value,
                Created = element.Element("created").Value.ToDateTime(),
                Description = element.Element("description").Value,
                Owner = element.Element("owner").Value,
                Privacy = (Privacy)element.Element("privacy").Value.ToInt(),
                Size = element.Element("size").Value.ToInt(),
                Title = element.Element("title").Value,
                Updated = element.Element("updated").Value.ToDateTime()
            };
            return _result;
        }

        public override string ToString()
        {
            return String.IsNullOrEmpty(Title) ? Aid : Title;
        }
    }

    [DataContract(Name = "Photo")]
    public class Photo : IPhoto
    {
        #region Implementation of IPhoto

        [DataMember(Name = "pid")]
        public string Pid { get; private set; }
        [DataMember(Name = "aid")]
        public string Aid { get; private set; }
        [DataMember(Name = "owner")]
        public string Owner { get; private set; }
        [DataMember(Name = "src")]
        public Uri Src { get; private set; }
        [DataMember(Name = "src_small")]
        public Uri SrcSmall { get; private set; }
        [DataMember(Name = "src_big")]
        public Uri SrcBig { get; private set; }
        [DataMember(Name = "created")]
        //    [JsonConverter(typeof(DateTimeConverter))]
        public DateTime Created { get; private set; }
        [DataMember(Name = "width")]
        public int Width { get; private set; }
        [DataMember(Name = "height")]
        public int Height { get; private set; }
        [DataMember(Name = "size")]
        public int Size { get; private set; }
        [DataMember(Name = "title")]
        public string Title { get; private set; }

        #endregion

        public static IPhoto Parse(JsonValue jObject)
        {
            var _result = new Photo
                              {
                                  Pid = jObject["pid"],
                                  Aid = jObject["aid"],
                                  Owner = jObject["owner"],
                                  Src = jObject["src"],
                                  SrcSmall = jObject["src_small"],
                                  SrcBig = jObject["src_big"],
                                  Created = jObject["created"].ToDateTime(),
                                  Width = jObject["width"].ToInt(),
                                  Height = jObject["height"].ToInt(),
                                  Size = jObject["size"].ToInt(),
                                  Title = jObject["title"]
                              };
            return _result;
        }

        public static IPhoto Parse(XElement element)
        {
            var _result = new Photo
            {
                Aid = element.Element("aid").Value,
                Created = element.Element("created").Value.ToDateTime(),
                Owner = element.Element("owner").Value,
                Size = element.Element("size").Value.ToInt(),
                Title = element.Element("title").Value,
                Height = element.Element("height").Value.ToInt(),
                Pid = element.Element("pid").Value,
                Src = element.Element("src").Value.ToUri(),
                SrcBig = element.Element("src_big").Value.ToUri(),
                SrcSmall = element.Element("src_small").Value.ToUri(),
                Width = element.Element("width").Value.ToInt(),
            };
            return _result;
        }

        public override string ToString()
        {
            return String.IsNullOrEmpty(Title) ? Pid : Title;
        }
    }

    [DataContract(Name = "Audio")]
    public class Audio : IAudio
    {
        #region Implementation of IAudio
        [DataMember(Name = "mid")]
        public string Mid { get; private set; }
        [DataMember(Name = "owner")]
        public string Owner { get; private set; }
        [DataMember(Name = "artist")]
        public string Artist { get; private set; }
        [DataMember(Name = "title")]
        public string Title { get; private set; }
        [DataMember(Name = "duration")]
        public int Duration { get; private set; }
        [DataMember(Name = "size")]
        public int Size { get; private set; }
        [DataMember(Name = "created")]
        //    [JsonConverter(typeof(DateTimeConverter))]
        public DateTime Created { get; private set; }
        [DataMember(Name = "link")]
        public Uri Link { get; private set; }

        #endregion

        public static IAudio Parse(JsonValue jObject)
        {
            var _result = new Audio
                              {
                                  Mid = jObject["mid"],
                                  Owner = jObject["owner"],
                                  Artist = jObject["artist"],
                                  Title = jObject["title"],
                                  Duration = jObject["duration"].ToInt(),
                                  Size = jObject["size"].ToInt(),
                                  Created = jObject["created"].ToDateTime(),
                                  Link = jObject["link"]
                              };
            return _result;
        }

        public static IAudio Parse(XElement element)
        {
            var _result = new Audio
            {
                Created = element.Element("created").Value.ToDateTime(),
                Owner = element.Element("owner").Value,
                Size = element.Element("size").Value.ToInt(),
                Title = element.Element("title").Value,
                Artist = element.Element("artist").Value,
                Duration = element.Element("duration").Value.ToInt(),
                Link = element.Element("link").Value.ToUri(),
                Mid = element.Element("mid").Value
            };
            return _result;
        }

        public override string ToString()
        {
            return String.IsNullOrEmpty(Title) ? Mid : Title;
        }
    }
}
